package com.cscec5b.inspection.service;

import com.cscec5b.inspection.dto.ProjectSyncDtos.*;
import com.cscec5b.inspection.entity.IdempotentRequest;
import com.cscec5b.inspection.entity.Project;
import com.cscec5b.inspection.repository.IdempotentRequestRepository;
import com.cscec5b.inspection.repository.ProjectRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;

@Service
public class ProjectSyncService {

    private final ProjectRepository projectRepo;
    private final IdempotentRequestRepository idemRepo;
    private final ObjectMapper om = new ObjectMapper();

    public ProjectSyncService(ProjectRepository projectRepo, IdempotentRequestRepository idemRepo) {
        this.projectRepo = projectRepo; this.idemRepo = idemRepo;
    }

    @Transactional
    public ProjectSyncResponse processSync(String clientId, String requestId, long ts, ProjectSyncRequest req) {
        String bodyHash = sha256Hex(json(req));
        Optional<IdempotentRequest> old = idemRepo.findByRequestId(requestId);
        if (old.isPresent()) {
            if (!old.get().getBodyHash().equalsIgnoreCase(bodyHash)) throw new ConflictException();
            try { return om.readValue(old.get().getResponseCache(), ProjectSyncResponse.class); }
            catch (Exception e) { throw new RuntimeException("deserialize cached response failed", e); }
        }

        List<Detail> details = new ArrayList<>(req.data.size());
        for (ProjectItem it : req.data) {
            try {
                upsert(it); // 只使用你现有字段
                details.add(new Detail(it.project_inner_number, true, null));
            } catch (Exception ex) {
                details.add(new Detail(it.project_inner_number, false, ex.getMessage()));
            }
        }

        ProjectSyncResponse resp = new ProjectSyncResponse(details);
        IdempotentRequest ir = new IdempotentRequest();
        ir.setRequestId(requestId);
        ir.setClientId(clientId);
        ir.setBodyHash(bodyHash);
        try { ir.setResponseCache(om.writeValueAsString(resp)); } catch (Exception e) { throw new RuntimeException(e); }
        idemRepo.save(ir);
        return resp;
    }

    private void upsert(ProjectItem it) {
        Project p = projectRepo.findByInnerNumber(it.project_inner_number).orElseGet(Project::new);
        if (p.getId() == null) p.setProjectInnerNumber(it.project_inner_number);

        p.setName(it.project_name);
        // 你表里没有传入的地址/施工/进度；如要保持为空即可
        // p.setProjectAddress(...); p.setProjectConstruction(...); p.setProjectSchedule(...);

        try {
            p.setProjectMembers(om.writeValueAsString(it.members));
            p.setSubprojects(om.writeValueAsString(it.subprojects));
        } catch (Exception e) {
            throw new IllegalArgumentException("serialize members/subprojects failed");
        }
        projectRepo.save(p);
    }

    private static String sha256Hex(String s) {
        try {
            var md = MessageDigest.getInstance("SHA-256");
            return java.util.HexFormat.of().formatHex(md.digest(s.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) { throw new RuntimeException(e); }
    }
    private String json(Object o) { try { return om.writeValueAsString(o); } catch (Exception e) { throw new RuntimeException(e); } }

    public static class ConflictException extends RuntimeException {}
}
